package com.wg.net.handle;

import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.wg.core.controller.ControllerMgr;
import com.wg.core.controller.IController;
import com.wg.core.counter.CounterMgr;
import com.wg.net.annotation.ResponseMapping;
import com.wg.net.peer.BaseServerToServerPeer;
import com.wg.net.operations.base.S2SOperationResponse;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

/**
 * 服务端TCP响应处理器管理器（单例模式）
 * <p>
 * 职责：
 * - 扫描并注册所有响应处理器（基于 {@link ResponseMapping} 注解）
 * - 分发TCP响应到对应的处理器
 * - 监控响应处理耗时与异常处理
 * - 提供响应处理标准化流程
 *
 * @author 少爷123
 */
public class HandleServerToServerResponseMgr {
    private static final Log log = LogFactory.get();

    /** 处理器映射表 <操作码, 处理器包装器> */
    private static final Map<Integer, HandleWrapper> HANDLER_MAP = new ConcurrentHashMap<>(128);
    /** 最大超时毫秒数（用于极端值过滤） */
    private static final long MAX_EXECUTION_TIME_MS = 100;

    // ------------------------------ 单例实现 ------------------------------
    private static class SingletonHolder {
        static final HandleServerToServerResponseMgr INSTANCE = new HandleServerToServerResponseMgr();
    }

    public static HandleServerToServerResponseMgr getInstance() {
        return SingletonHolder.INSTANCE;
    }

    private HandleServerToServerResponseMgr() {
        // 私有构造防止外部实例化
    }

    // ------------------------------ 初始化 ------------------------------
    /**
     * 初始化响应处理器（扫描指定包路径下的处理器类）
     *
     * @param packageName 扫描包路径（如 "com.wg.net.handle"）
     * @throws IllegalStateException 初始化失败时抛出
     */
    public void init(String packageName) {
        if (StrUtil.isBlank(packageName)) {
            throw new IllegalArgumentException("包路径不能为空");
        }

        if (!HANDLER_MAP.isEmpty()) {
            log.warn("S2S请求处理器已初始化，跳过重复初始化");
            return;
        }

        try {
            Set<Class<?>> handlerClasses = ClassUtil.scanPackageBySuper(
                    packageName, IHandleS2SResponse.class);
            registerHandlers(handlerClasses);
        } catch (Exception e) {
            log.error("S2S响应处理器初始化失败 | 包路径={}", packageName, e);
            throw new IllegalStateException("S2S响应处理器初始化失败", e);
        }
    }

    /**
     * 注册处理器（内部方法）
     */
    private void registerHandlers(Set<Class<?>> handlerClasses) {
        for (Class<?> clazz : handlerClasses) {
            // 跳过接口、抽象类
            if (!ClassUtil.isNormalClass(clazz))
                continue;

            // 解析注解
            ResponseMapping annotation = clazz.getAnnotation(ResponseMapping.class);
            if (annotation == null) {
                log.warn("处理器类缺少ResponseMapping注解 | {}", clazz.getName());
                continue;
            }

            int opCode = annotation.code();
            validateOpCode(opCode, clazz);

            HandleWrapper wrapper = createHandlerWrapper(clazz, annotation);
            HANDLER_MAP.put(opCode, wrapper);
        }
    }

    /**
     * 校验操作码合法性
     */
    private void validateOpCode(int opCode, Class<?> clazz) {
        // 操作码范围校验
        if (opCode <= 0) {
            log.error("无效操作码 | 类={}, 操作码={}（必须＞0）", clazz.getName(), opCode);
            throw new IllegalArgumentException("操作码必须大于0");
        }

        // 操作码重复校验
        if (HANDLER_MAP.containsKey(opCode)) {
            String conflictClass = HANDLER_MAP.get(opCode).handler.getClass().getName();
            String errorMsg = StrUtil.format(
                    "操作码冲突 | 操作码={}, 冲突类={}, 当前类={}",
                    opCode, conflictClass, clazz.getName());
            log.error(errorMsg);
            throw new IllegalStateException(errorMsg);
        }
    }

    /**
     * 创建处理器包装器
     */
    private HandleWrapper createHandlerWrapper(Class<?> clazz, ResponseMapping annotation) {
        try {
            HandleWrapper wrapper = new HandleWrapper();
            wrapper.handler = (IHandleS2SResponse) ReflectUtil.newInstance(clazz);

            Class<? extends IController> controllerClass = annotation.controller();
            if (controllerClass != null && controllerClass != IController.class) {
                wrapper.controller = ControllerMgr.getInstance().getController(controllerClass);
            }

            long maxMs = annotation.maxExeTimeMs();
            if (maxMs <= 0) {
                maxMs = MAX_EXECUTION_TIME_MS;
            } 
            wrapper.maxExecutionNs = TimeUnit.MILLISECONDS.toNanos(maxMs);
            return wrapper;
        } catch (Exception e) {
            log.error("处理器实例化失败 | 类={}", clazz.getName(), e);
            throw new RuntimeException("处理器实例化失败", e);
        }
    }

    // ------------------------------ 响应执行 ------------------------------
    /**
     * 执行响应处理（入口方法）
     *
     * @param peer     对端服务器实例
     * @param response 待处理响应
     */
    public void execute(BaseServerToServerPeer peer, S2SOperationResponse response) {
        final int opCode = response.getOpCode();
        HandleWrapper wrapper = HANDLER_MAP.get(opCode);

        if (wrapper == null) {
            log.error("未知操作码 | 操作码={}, 来源={}:{}", opCode, peer.getRemoteIp(), peer.getRemotePort());
        } else {
            wrapper.handle(peer, response);
        }
    }

    // ------------------------------ 内部类：处理器包装器 ------------------------------
    /**
     * 处理器包装器（封装处理器与其执行环境）
     */
    private static class HandleWrapper {
        /** 响应处理器实例 */
        IHandleS2SResponse handler;
        /** 关联控制器（可为空） */
        IController controller;
        /** 最大允许执行时间（纳秒） */
        long maxExecutionNs;

        /**
         * 异步处理响应（若有关联控制器，则提交到控制器的协程池）
         */
        void handle(BaseServerToServerPeer peer, S2SOperationResponse response) {
            if (controller != null && controller.getFiber() != null) {
                controller.getFiber().enqueue(() -> processResponse(peer, response));
            } else {
                // 无控制器时直接在当前线程执行
                processResponse(peer, response);
            }
        }

        /**
         * 实际处理逻辑（包含耗时监控与异常处理）
         */
        private void processResponse(BaseServerToServerPeer peer, S2SOperationResponse response) {
            long queueTimeNs = response.getHandleInterval().intervalRestart();
            try {
                handler.execute(peer, response);
            } catch (Exception e) {
                log.error("响应处理器异常 | 操作码={}, 处理器={}",
                        response.getOpCode(), handler.getClass().getName(), e);
            } finally {
                long processTimeNs = response.getHandleInterval().interval();
                logExecutionTime(processTimeNs, queueTimeNs + processTimeNs, handler.getClass().getSimpleName());
            }
        }

        /**
         * 记录执行耗时（区分正常日志与超时日志）
         */
        private void logExecutionTime(long processTimeNs, long totalTimeNs, String handlerName) {
            double processTimeMs = processTimeNs / 1_000_000.0;
            double totalTimeMs = totalTimeNs / 1_000_000.0;
            String message = StrUtil.format("请求处理完毕 | 处理器={}, 业务耗时={}ms, 总耗时={}ms",
                    handlerName,
                    String.format("%.3f", processTimeMs),
                    String.format("%.3f", totalTimeMs));

            // 判断是否超时并记录相应日志
            if (processTimeNs > maxExecutionNs) {
                log.warn(message + " [超时]");
            } else {
                log.debug(message);
            }

            // 添加监控指标（总耗时）
            CounterMgr.getInstance().getSsAverage().addValue(totalTimeNs);
        }
    }
}